package com.newcoder.service.impl;

import com.newcoder.entity.Event;
import com.newcoder.entity.User;
import com.newcoder.event.EventProducer;
import com.newcoder.mapper.UserMapper;
import com.newcoder.util.CommunityConstant;
import com.newcoder.util.HostHolder;
import com.newcoder.util.RedisKeyUtil;
import com.newcoder.util.ResponseWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FollowServiceImpl implements CommunityConstant {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private EventProducer eventProducer;


    public ResponseWrapper follow(Integer userId, Integer entityType, Integer entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                operations.multi();

                operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());

                return operations.exec();
            }
        });

        // 触发关注事件
        Event event = new Event()
                .setTopic(TOPIC_FOLLOW)
                .setUserId(userId)
                .setEntityType(entityType)
                .setEntityId(entityId)
                .setEntityUserId(entityId);
        eventProducer.fireEvent(event);

        return ResponseWrapper.markCustom(true, 200,"操作成功！");
    }

    public ResponseWrapper unfollow(Integer userId, Integer entityType, Integer entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                operations.multi();

                operations.opsForZSet().remove(followeeKey, entityId);
                operations.opsForZSet().remove(followerKey, userId);

                return operations.exec();
            }
        });

        return ResponseWrapper.markCustom(true, 200,"操作成功！");
    }

    //查询关注的人
    public ResponseWrapper selectFolloweesPage(Integer userId, Integer currentPage, Integer pageSize) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在!");
        }

        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, currentPage, currentPage + pageSize - 1);

        if (targetIds == null) {
            return null;
        }

        List<Map<String, Object>> userList = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User u = userMapper.selectById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);
            map.put("followTime", new Date(score.longValue()));
            userList.add(map);
        }
        if (userList != null) {
            for (Map<String, Object> map : userList) {
                User u = (User) map.get("user");
                map.put("hasFollowed", hasFollowed(userId, ENTITY_TYPE_USER, u.getId()));
            }
        }

        ResponseWrapper wrapper = ResponseWrapper.markSuccess();
        wrapper.getData().put("user", user);
        wrapper.getData().put("userList", userList);
        return wrapper;
    }

    //查询关注我的人（查询粉丝）
    public ResponseWrapper selectFollowersPage(Integer userId, Integer currentPage, Integer pageSize) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在!");
        }

        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, currentPage, currentPage + pageSize - 1);

        if (targetIds == null) {
            return null;
        }

        List<Map<String, Object>> userList = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User u = userMapper.selectById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
            map.put("followTime", new Date(score.longValue()));
            userList.add(map);
        }

        if (userList != null) {
            for (Map<String, Object> map : userList) {
                User u = (User) map.get("user");
                map.put("hasFollowed", hasFollowed(userId, ENTITY_TYPE_USER, u.getId()));
            }
        }

        ResponseWrapper wrapper = ResponseWrapper.markSuccess();
        wrapper.getData().put("user", user);
        wrapper.getData().put("userList", userList);
        return wrapper;
    }



    // 查询关注的实体的数量
    public long findFolloweeCount(int userId, int entityType) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    // 查询实体的粉丝的数量
    public long findFollowerCount(int entityType, int entityId) {
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    // 查询当前用户是否已关注该实体
    public boolean hasFollowed(int userId, int entityType, int entityId) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }
}
